package com.xianyun.site.support.executor.commond;

import com.alibaba.cola.exception.BizException;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dm.model.v20151123.SingleSendMailRequest;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.xianyun.common.core.utils.DateToolUtils;
import com.xianyun.common.core.utils.EncryptUtils;
import com.xianyun.common.redis.service.RedisService;
import com.xianyun.site.support.common.constant.MessageConstants;
import com.xianyun.site.support.common.constant.SmtpServiceConstants;
import com.xianyun.site.support.common.exception.SmtpException;
import com.xianyun.site.support.convertor.SmtpConvertor;
import com.xianyun.site.support.domain.model.SmtpMessage;
import com.xianyun.site.support.dto.SmtpReceiveCmd;
import com.xianyun.site.support.dto.clientobject.SmtpMessageCO;
import com.xianyun.site.support.executor.handle.smtp.SmtpContent;
import com.xianyun.site.support.executor.handle.smtp.v20201108.config.SmtpSendType;
import com.xianyun.site.support.gatewayimpl.database.SmtpSendLogMapper;
import com.xianyun.site.support.gatewayimpl.database.domainobject.SmtpSendLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.TimeUnit;

/**
 * @author mac_zyj
 */
@Slf4j
@Component
public class SmtpReceiveCmdExo {
    @Value("${alibaba.cloud.access-key}")
    private String accessKey;

    @Value("${alibaba.cloud.secret-key}")
    private String secretKey;

    @Value("${alibaba.cloud.smtp.regionId}")
    private String regionId;

    private IAcsClient client;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SmtpSendLogMapper smtpSendLogMapper;
    
    
    public void execute(SmtpReceiveCmd receiveCmd){
        IAcsClient client = getClient();
        SmtpSendType sendType = SmtpSendType.getSendTypeById(receiveCmd.getCheckParam().getUserAction());
        SmtpContent smtpContent = new SmtpContent(sendType.getType());
        SingleSendMailRequest request=smtpContent.sendSingleMailRequest(receiveCmd);
        actionAfterSent(request,receiveCmd.getSmtpMessage(),sendType);
    }

    private void actionAfterSent(SingleSendMailRequest request, SmtpMessageCO message, SmtpSendType sendType){
        try {
            SmtpMessage smtpMessage = SmtpConvertor.toEntity(message);
            String redisCheckKey = smtpMessage.getRedisCheckKey();
            String toAddress = message.getToAddress();
            client.getAcsResponse(request);
            if (sendType.equals(SmtpSendType.CHECK_TYPE)){
                String repeatCheckKey = smtpMessage.getRedisCheckKey(MessageConstants.REPEAT_CHECK);
                String timesCheckKey = smtpMessage.getRedisCheckKey(MessageConstants.TIMES_CHECK);
                setRedisCheck(repeatCheckKey,message.getCheckCode(),redisCheckKey,timesCheckKey);
            }
            saveSmtpSendLog(message.getTransactionId(),request.getAccountName(),toAddress,request.getTagName(),request.getHtmlBody());
            log.info(message.getConditionName()+"---"+"emailSend:"+toAddress+"---邮件已发送");
        }catch (ClientException e) {
            log.warn("Smtp ClientException:{}", e.getErrMsg());
            throw new SmtpException("客户端设置异常");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    
    private void setRedisCheck(String repeatCheckKey,String code,String redisCheckKey,String timesCheckKey){
        try {
            //设置邮件发送间隔时间
            redisService.setCacheObject(repeatCheckKey, null, SmtpServiceConstants.SMTP_REDIS_EXPIRATION, TimeUnit.MINUTES);
            Integer redisGetTimes = redisService.getCacheObject(timesCheckKey);
            int sendTimesInLastHour= 0;
            if(null!=redisGetTimes){
                sendTimesInLastHour=redisGetTimes;
            }
            //设置当前邮件发送次数间隔时间
            redisService.setCacheObject(timesCheckKey,++sendTimesInLastHour, SmtpServiceConstants.CHECK_SMTP_SEND_TIMES_TIME, TimeUnit.HOURS);
            //设置邮件存活时间
            redisService.setCacheObject(redisCheckKey, EncryptUtils.encrypt(code), SmtpServiceConstants.SMTP_USE_EXPIRATION, TimeUnit.MINUTES);
        } catch (BizException e)
        {
            log.warn("BizException with error code:{},error message:{}",e.getErrCode(),e.getMessage());
        }
        catch (Exception ex) {
            log.error("System error"+ex.getMessage(),ex);
        }
    }

    /**
     * 保存邮件发送记录
     * @param smtpNo 编号
     * @param accountName 账户名称
     * @param toAddress 发送地址
     * @param tagName 标签
     * @param httpBody 邮件体
     */
    @Transactional(rollbackFor = RuntimeException.class)
    void saveSmtpSendLog(String smtpNo, String accountName, String toAddress, String tagName, String httpBody){
        SmtpSendLog smtpSendLog = new SmtpSendLog();
        smtpSendLog.setSmtpNo(smtpNo);
        smtpSendLog.setAccountName(accountName);
        smtpSendLog.setFrom(toAddress);
        smtpSendLog.setTag(tagName);
        smtpSendLog.setHttpBody(httpBody);
        smtpSendLog.setSendTime(DateToolUtils.getNowDate());
        smtpSendLogMapper.insertSmtpSendLog(smtpSendLog);
    }

    private IAcsClient getClient(){
        while (null == client){
            setAcsClient();
        }
        return client;
    }

    private synchronized void setAcsClient(){
        // 如果是除杭州region外的其它region（如新加坡、澳洲Region），需要将下面的”cn-hangzhou”替换为”ap-southeast-1”、或”ap-southeast-2”。
        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKey, secretKey);
        client = new DefaultAcsClient(profile);
    }
}
